#include <speex/speex.h>
#include <stdio.h>
#include <alsa/asoundlib.h>

#define ALSA_PCM_NEW_HW_PARAMS_API

int rc; 
snd_pcm_t *handle; 		
snd_pcm_uframes_t frames; 
int size; 		
char *buffer; 
int channels = 2;//立体声
int rate=44100;//采样率

/****************************************************************************************
*   函数名: init_alsa_play
*   输  入: 无
*   输  出: 无
*   功能说明：alsa音频播放器初始化
*
*       
******************************************************************************************/
void init_alsa_play()
{
		snd_pcm_hw_params_t *params; 
		unsigned int val; 
		int dir; 
				
		/* Open PCM device for playback. */
		rc=snd_pcm_open(&handle,"default", SND_PCM_STREAM_PLAYBACK, 0);
		if (rc< 0) 
		{ 
			fprintf(stderr,  "unable to open pcm device: %s\n",    snd_strerror(rc));
			exit(1); 
		} 
		 
		/* Allocate a hardware parameters object. */
		 snd_pcm_hw_params_alloca(&params); 
		/* Fill it in with default values. */
		 snd_pcm_hw_params_any(handle, params);
		 /* Set the desired hardware parameters. */ 

		/* Interleaved mode */ 
		snd_pcm_hw_params_set_access(handle,params, SND_PCM_ACCESS_RW_INTERLEAVED); 

		/* Signed 16-bit little-endian format 格式*/ 
		snd_pcm_hw_params_set_format(handle,params, SND_PCM_FORMAT_S16_LE); 


		/* Two channels (stereo) 声道*/  
		snd_pcm_hw_params_set_channels(handle, params, channels); 
		/* 44100 bits/second sampling rate (CD quality) 采样率设置*/ 
		snd_pcm_hw_params_set_rate_near(handle,params, &rate, &dir);  /* Set period size to 32 frames. */ 
		frames = 80; 
		snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
		/* Write the parameters to the driver */
		 rc = snd_pcm_hw_params(handle, params);
		 if (rc < 0) 
		 {   
				fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));   
				exit(1); 
		}

		/*Use a buffer large enough to hold one period*/
		snd_pcm_hw_params_get_period_size(params, &frames,  &dir); //32个采样点算一帧
		size = frames * (channels);
		/* 2 bytes/sample, 2 channels */ 
		buffer = (char *) malloc(size); 
		/* We want to loop for 5 seconds */
		snd_pcm_hw_params_get_period_time(params, &val, &dir); 
}

/*The frame size in hardcoded for this sample code but it doesn't have to be*/
#define FRAME_SIZE 160
int main(int argc, char **argv)
{
   char *outFile;
   char *inFile[1];
// FILE *fout;
   FILE *fin[1];
   /*Holds the audio that will be written to file (16 bits per sample)*/
   short out[FRAME_SIZE];
   /*Speex handle samples as float, so we need an array of floats*/
   float output[FRAME_SIZE];
   char cbits[200];
   int nbBytes;
   /*Holds the state of the decoder*/
   void *state;
   /*Holds bits so they can be read and written to by the Speex routines*/
   SpeexBits bits;
   int i, tmp;
   
   if((argc != 2))
   {
      printf("error!\n");
      printf("usage: sampledec *.spx \n");
      return 1;
   }
      
   printf("%s: start\n", __func__);
	 init_alsa_play();
	
   /*Create a new decoder state in narrowband mode*/
   state = speex_decoder_init(&speex_nb_mode);

   /*Set the perceptual enhancement on*/
   tmp=1;
   speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp);
   //printf("%s: 22222222\n", __func__);
	 inFile[0]	= argv[1];
	 //inFile[1]	= argv[2];	 
//   outFile = argv[1];
   //fout = fopen(outFile, "w");
   fin[0] = fopen(inFile[0], "r");//打开输入的spx文件
   
   if(fin[0] ==NULL)
   {
     perror("打开文件错误");
     exit(1);
   }
   
   //printf("%s: 3333333\n", __func__);
   /*Initialization of the structure that holds the bits*/
   speex_bits_init(&bits);
   //printf("%s: 4444444\n", __func__);   
   while (1)
   {   //printf("%s: 55555\n", __func__);
      //printf("%s: 1111111\n", __func__);
      /*Read the size encoded by sampleenc, this part will likely be 
        different in your application*/
      fread(&nbBytes, sizeof(int), 1, fin[0]);
      //fprintf (stderr, "nbBytes: %d\n", nbBytes);
      if (feof(fin[0]))
         break;
         //printf("%s: 666\n", __func__);
      /*Read the "packet" encoded by sampleenc*/
      fread(cbits, 1, nbBytes, fin[0]);
      /*Copy the data into the bit-stream struct*/
      speex_bits_read_from(&bits, cbits, nbBytes);

      /*Decode the data*/
      speex_decode(state, &bits, output);

      /*Copy from float to short (16 bits) for output*/
      for (i=0;i<FRAME_SIZE;i++)
         out[i]=output[i];
   //printf("%s: 88888\n", __func__);
      /*Write the decoded audio to file*/
      //fwrite(out, sizeof(short), FRAME_SIZE, fout);
      
      snd_pcm_writei(handle, out, 80); 
         //printf("%s: 99999\n", __func__);
   }
   
   /*Destroy the decoder state*/
   speex_decoder_destroy(state);
   /*Destroy the bit-stream truct*/
   speex_bits_destroy(&bits);
   fclose(fin[0]);
   return 0;
}
